package com.newtouch.fileupload.service.impl;


import com.newtouch.fileupload.entity.FileRepo;
import com.newtouch.fileupload.entity.VideoRepo;
import com.newtouch.fileupload.model.FileEO;
import com.newtouch.fileupload.model.FileReq;
import com.newtouch.fileupload.model.VideoEO;
import com.newtouch.fileupload.service.FileUploadService;
import com.newtouch.fileupload.util.FileMd5Util;
import com.newtouch.fileupload.util.NameUtil;
import com.newtouch.fileupload.util.ShortIds;
import org.apache.tomcat.util.http.fileupload.FileUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Service
public class FileUploadServiceImpl implements FileUploadService {

    /**
     * 注意locus-api与ntl-mgr-api部署在不同机器时,此处需借助第三存储实现,诸如NAS、OOS等
     */
    //视频文件存目录
//    public static final String VIDEO_PATH = "./data/mp4";
    public static final String VIDEO_PATH = "E:\\视频文件\\";


    @Autowired
    FileRepo fileRepo;
    @Autowired
    VideoRepo videoRepo;

    @Override
    public Map<String, Object> findByTraceNo(String traceNo) {
        FileEO uploadFile = fileRepo.findByTraceNo(traceNo);

        Map<String, Object> map = null;
        if (uploadFile == null) {
            //没有上传过文件
            map = new HashMap<>();
            map.put("flag", 0);
            map.put("message", "没有上传过文件");
        } else {
            //上传过文件，判断文件现在是否存在
            File file = new File(uploadFile.getFilePath());

            if (file.exists()) {
                if (uploadFile.getFileStatus() == 1) {
                    //文件只上传了一部分
                    map = new HashMap<>();
                    map.put("flag", 1);
                    map.put("message", "文件只上传了一部分");
                } else if (uploadFile.getFileStatus() == 2) {
                    //文件早已上传完整
                    map = new HashMap<>();
                    map.put("flag" , 2);
                    map.put("message", "文件早已上传完整");
                }
            } else {
                map = new HashMap<>();
                map.put("flag", 0);
                map.put("traceNo", traceNo);
            }
        }
        return map;
    }


    @Override
    public Map<String, Object> realUpload(FileReq req, MultipartFile multipartFile) throws Exception {
        String action = req.getAction();
        String traceNo = req.getTraceNo();
        int index = Integer.valueOf(req.getIndex());
        String partMd5 = req.getPartMd5();
        String md5 = req.getMd5();
        int total = Integer.valueOf(req.getTotal());
        String fileName = req.getName();
        String size = req.getSize();
        String suffix = NameUtil.getExtensionName(fileName);

        String saveDirectory = VIDEO_PATH + File.separator + traceNo;//分片存储目录
        String filePath = VIDEO_PATH + File.separator + traceNo + "." + suffix;

        //验证路径是否存在，不存在则创建目录
        File path = new File(saveDirectory);
        if (!path.exists()) {
            path.mkdirs();
        }
        //文件分片位置
        File file = new File(saveDirectory, traceNo + "_" + index);

        //根据action不同执行不同操作. check:校验分片是否上传过; upload:直接上传分片
        Map<String, Object> map = null;
        if ("check".equals(action)) {
            String md5Str = FileMd5Util.getFileMD5(file);
            if (md5Str != null && md5Str.length() == 31) {
                System.out.println("check length =" + partMd5.length() + " md5Str length" + md5Str.length() + "   " + partMd5 + " " + md5Str);
                md5Str = "0" + md5Str;
            }
            if (md5Str != null && md5Str.equals(partMd5)) {
                //分片已上传过
                map = new HashMap<>();
                map.put("flag", "1");
                map.put("traceNo", traceNo);
                if(index != total)
                    return map;
            } else {
                //分片未上传
                map = new HashMap<>();
                map.put("flag", "0");
                map.put("traceNo", traceNo);
                return map;
            }
        } else if("upload".equals(action)) {
            //分片上传过程中出错,有残余时需删除分块后,重新上传
            if (file.exists()) {
                file.delete();
            }
            multipartFile.transferTo(new File(saveDirectory, traceNo + "_" + index));
            map = new HashMap<>();
            map.put("flag", "1");
            map.put("traceNo", traceNo);
            if(index != total)
                return map;
        }

        if (path.isDirectory()) {
            File[] fileArray = path.listFiles();
            if (fileArray != null) {
                if (fileArray.length == total) {
                    //分块全部上传完毕,合并
                    File newFile = new File(filePath);
                    FileOutputStream outputStream = new FileOutputStream(newFile, true);//文件追加写入
                    byte[] byt = new byte[10 * 1024 * 1024];
                    int len;
                    FileInputStream temp = null;//分片文件
                    for (int i = 0; i < total; i++) {
                        int j = i + 1;
                        temp = new FileInputStream(new File(saveDirectory, traceNo + "_" + j));
                        while ((len = temp.read(byt)) != -1) {
                            outputStream.write(byt, 0, len);
                        }
                        //关闭流
                        temp.close();
                    }
                    outputStream.close();
                    size = newFile.length() + "";
                    //删除分片文件
                    FileUtils.deleteDirectory(path);
                    //修改FileRes记录为上传成功
                    FileEO uploadFile = new FileEO();
                    uploadFile.setTraceNo(traceNo);
                    uploadFile.setFileStatus(2);
                    uploadFile.setFileName(fileName);
                    uploadFile.setFileMd5(md5);
                    uploadFile.setFileSuffix(suffix);
                    uploadFile.setFilePath(filePath);
                    uploadFile.setFileSize(size);
                    fileRepo.save(uploadFile);

                    //保存video
                    VideoEO videoEO = new VideoEO();
                    videoEO.setId(ShortIds.get());
                    videoEO.setTraceNo(traceNo);
                    videoEO.setStatus("ok");
//                    videoEO.setAllTime(DateUtil.getTimeStr(eTime - bTime));
                    videoEO.setPath(traceNo + "." + suffix);
                    videoEO.setCreatedDt(new Date());
                    videoEO.setUpdatedDt(new Date());
                    videoRepo.save(videoEO);


                    map=new HashMap<>();
                    map.put("traceNo", traceNo);
                    map.put("flag", "2");

                    return map;
                } else if(index == 1) {
                    //文件第一个分片上传时记录到数据库
                    FileEO uploadFile = new FileEO();
                    uploadFile.setFileMd5(md5);
                    String name = NameUtil.getFileNameNoEx(fileName);

                    if (name.length() > 32) {
                        name = name.substring(0, 32);
                    }
                    uploadFile.setFileName(name);
                    uploadFile.setFileSuffix(suffix);
                    uploadFile.setTraceNo(traceNo);
                    uploadFile.setFilePath(filePath);
                    uploadFile.setFileSize(size);
                    uploadFile.setFileStatus(1);

                    fileRepo.save(uploadFile);
                }
            }
        }
        return map;
    }
}
